<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>函数预编译</title>
</head>

<body>

</body>

</html>
<script>
    function fn(a, c) {
        console.log(a) // function a(){}
        var a = 123;
        console.log(a); //123
        console.log(c); //function c(){}
        function a() {}
        if (false) {
            var d = 678;
        }
        console.log(d); //undefined
        console.log(b); //undefined 

        var b = function() {}
        console.log(b) //function(){}
        function c() {}
        console.log(c) //functionc(){}
    }
    fn(1, 2)
        /*
            预编译原理：第一步：创建AO作用域对象

            第二步：提升所有的形参和变量，此时
            {
                a:undefined,
                b:undefined,
                c:undefined,
                d:undefined
            }

            第三步：形参替换，因为执行的是fn(1,2)，所以此时会替换掉a跟c的形参        
            {
                a:1,
                b:undefined,
                c:2,
                d:undefined
            }

            第四步：寻找函数声明，在fn中声明了两个函数（var b=function(){}为函数表达式，非函数声明），分别是function a与function c，他们会替换掉a,c的值，此时：  
            {
                a:function(){},
                b:undefined,
                c:function(){},
                d:undefined
            }

            到此预编译结束，函数开始执行。所以输出结果为注释内容。
        */
</script>